import pandas as pd
import numpy as np
from typing import Dict, List, Any

class DataProcessor:
    """数据处理工具类"""
    
    def analyze_dataset(self, df: pd.DataFrame) -> Dict[str, Any]:
        """分析数据集基本信息"""
        analysis = {
            'basic_info': self._get_basic_info(df),
            'column_types': self._analyze_column_types(df),
            'missing_values': self._analyze_missing_values(df),
            'chart_recommendations': self._recommend_charts(df)
        }
        return analysis
    
    def _get_basic_info(self, df: pd.DataFrame) -> Dict[str, Any]:
        """获取基本信息"""
        return {
            'rows': len(df),
            'columns': len(df.columns),
            'memory_usage': f"{df.memory_usage(deep=True).sum() / 1024 / 1024:.2f} MB",
            'column_names': df.columns.tolist()
        }
    
    def _analyze_column_types(self, df: pd.DataFrame) -> Dict[str, List[str]]:
        """分析列数据类型"""
        numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
        categorical_cols = df.select_dtypes(include=['object']).columns.tolist()
        datetime_cols = []
        
        # 尝试检测日期时间列
        for col in df.columns:
            if df[col].dtype == 'object':
                try:
                    pd.to_datetime(df[col].head(100), errors='raise')
                    datetime_cols.append(col)
                    if col in categorical_cols:
                        categorical_cols.remove(col)
                except:
                    pass
        
        return {
            'numeric': numeric_cols,
            'categorical': categorical_cols,
            'datetime': datetime_cols
        }
    
    def _analyze_missing_values(self, df: pd.DataFrame) -> Dict[str, Any]:
        """分析缺失值"""
        missing_counts = df.isnull().sum()
        missing_percentages = (missing_counts / len(df) * 100).round(2)
        
        missing_info = []
        for col in df.columns:
            if missing_counts[col] > 0:
                missing_info.append({
                    'column': col,
                    'count': int(missing_counts[col]),
                    'percentage': float(missing_percentages[col])
                })
        
        return {
            'total_missing': int(missing_counts.sum()),
            'columns_with_missing': len(missing_info),
            'details': missing_info
        }
    
    def _recommend_charts(self, df: pd.DataFrame) -> List[Dict[str, Any]]:
        """智能推荐图表类型"""
        column_types = self._analyze_column_types(df)
        recommendations = []
        
        numeric_cols = column_types['numeric']
        categorical_cols = column_types['categorical']
        
        # 直方图 - 适用于数值列
        if numeric_cols:
            recommendations.append({
                'type': 'histogram',
                'name': '直方图',
                'description': '显示数值分布',
                'suitable_for': numeric_cols[:3],  # 推荐前3个数值列
                'requires': ['x_column']
            })
        
        # 箱线图 - 适用于数值列
        if numeric_cols:
            recommendations.append({
                'type': 'boxplot',
                'name': '箱线图',
                'description': '显示数据分布和异常值',
                'suitable_for': numeric_cols[:3],
                'requires': ['x_column']
            })
        
        # 柱状图 - 适用于分类列
        if categorical_cols:
            recommendations.append({
                'type': 'bar',
                'name': '柱状图',
                'description': '显示类别计数或统计',
                'suitable_for': categorical_cols[:3],
                'requires': ['x_column']
            })
        
        # 饼图 - 适用于分类列
        if categorical_cols:
            recommendations.append({
                'type': 'pie',
                'name': '饼图',
                'description': '显示类别占比',
                'suitable_for': categorical_cols[:3],
                'requires': ['x_column']
            })
        
        # 散点图 - 需要两个数值列
        if len(numeric_cols) >= 2:
            recommendations.append({
                'type': 'scatter',
                'name': '散点图',
                'description': '显示两个变量关系',
                'suitable_for': numeric_cols[:2],
                'requires': ['x_column', 'y_column']
            })
        
        # 相关性热力图 - 需要多个数值列
        if len(numeric_cols) >= 3:
            recommendations.append({
                'type': 'correlation',
                'name': '相关性热力图',
                'description': '显示变量间相关性',
                'suitable_for': numeric_cols,
                'requires': []
            })
        
        # 线图 - 适用于时间序列或有序数据
        if numeric_cols:
            recommendations.append({
                'type': 'line',
                'name': '折线图',
                'description': '显示趋势变化',
                'suitable_for': numeric_cols[:2],
                'requires': ['x_column', 'y_column']
            })
        
        return recommendations
    
    def generate_statistics(self, df: pd.DataFrame) -> Dict[str, Any]:
        """生成统计信息"""
        column_types = self._analyze_column_types(df)
        
        stats = {
            'numeric_stats': {},
            'categorical_stats': {},
            'overall_stats': {
                'total_rows': len(df),
                'total_columns': len(df.columns),
                'missing_values': df.isnull().sum().sum(),
                'duplicate_rows': df.duplicated().sum()
            }
        }
        
        # 数值列统计
        for col in column_types['numeric']:
            stats['numeric_stats'][col] = {
                'count': int(df[col].count()),
                'mean': float(df[col].mean()) if not df[col].empty else 0,
                'std': float(df[col].std()) if not df[col].empty else 0,
                'min': float(df[col].min()) if not df[col].empty else 0,
                'max': float(df[col].max()) if not df[col].empty else 0,
                'q25': float(df[col].quantile(0.25)) if not df[col].empty else 0,
                'q50': float(df[col].quantile(0.50)) if not df[col].empty else 0,
                'q75': float(df[col].quantile(0.75)) if not df[col].empty else 0
            }
        
        # 分类列统计
        for col in column_types['categorical']:
            value_counts = df[col].value_counts().head(10)
            stats['categorical_stats'][col] = {
                'unique_count': int(df[col].nunique()),
                'most_frequent': value_counts.index[0] if not value_counts.empty else None,
                'top_values': [
                    {'value': str(val), 'count': int(count)} 
                    for val, count in value_counts.items()
                ]
            }
        
        return stats